home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / gcc / ixemulsrc.lha / ixemul-41.4 / library / pipe.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  13KB  |  517 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *  $Id: pipe.c,v 1.4 1994/06/19 15:14:19 rluebbert Exp $
  21.  *
  22.  *  $Log: pipe.c,v $
  23.  *  Revision 1.4  1994/06/19  15:14:19  rluebbert
  24.  *  *** empty log message ***
  25.  *
  26.  *  Revision 1.2  1992/07/04  19:21:08  mwild
  27.  *  (finally..) fix the bug which could cause pipe readers/writers to deadlock
  28.  *
  29.  * Revision 1.1  1992/05/14  19:55:40  mwild
  30.  * Initial revision
  31.  *
  32.  */
  33.  
  34. #define KERNEL
  35. #include "ixemul.h"
  36. #include "kprintf.h"
  37.  
  38. #include <sys/ioctl.h>
  39. #include "select.h"
  40.  
  41. /* information for the temporary implementation of pipes.
  42.    PIPE: has the big disadvantage that it blocks in the most unpleasent
  43.    situations, and doesn't send SIGPIPE to processes that write on
  44.    readerless pipes. Unacceptable for this library ;-)) */
  45.  
  46. #define PIPE_SIZE    5120
  47.  
  48. struct tmp_pipe {
  49.   u_short    tp_flags;        /* see below */
  50.   u_char    tp_buffer[PIPE_SIZE];
  51.   u_char    *tp_reader, *tp_writer;    /* buffer pointers.
  52.                        when tp_reader==tp_writer, no data
  53.                        is available */
  54. };
  55.  
  56. #define TPF_NO_READER    (1<<0)
  57. #define TPF_NO_WRITER    (1<<1)
  58. #define TPF_LOCKED    (1<<2)
  59. #define TPF_WANT_LOCK    (1<<3)
  60.  
  61. static int __pread(), __pwrite(), __pselect(), __pioctl(), __pclose();
  62. static struct tmp_pipe *__pinit();
  63.  
  64. static inline void
  65. __get_pipe (struct file *f)
  66. {
  67.   struct tmp_pipe *tp = f->f_tp;
  68.  
  69. retry:  
  70.   Forbid ();
  71.   for (;;)
  72.     {
  73.       if (!(tp->tp_flags & TPF_LOCKED))
  74.         {
  75.           tp->tp_flags &= ~TPF_WANT_LOCK;
  76.           tp->tp_flags |= TPF_LOCKED;
  77.           /* got it ! */
  78.           break;
  79.     }
  80.       tp->tp_flags |= TPF_WANT_LOCK;
  81.       KPRINTF_DISABLED (("__get_pipe: going to sleep\n"));
  82.       if (ix_sleep (&tp->tp_flags, "get_pipe") < 0)
  83.         {
  84.       KPRINTF_DISABLED (("__get_pipe: interrupted\n"));
  85.       Permit ();
  86.       setrun (FindTask (0));
  87.           goto retry;
  88.         }
  89.       KPRINTF_DISABLED (("__get_pipe: back from sleep (not interrupted)\n"));
  90.       /* have to always recheck whether we really got the lock */
  91.     }
  92.   Permit ();      
  93. }
  94.  
  95. static inline void
  96. __release_pipe (struct file *f)
  97. {
  98.   struct tmp_pipe *tp = f->f_tp;
  99.  
  100.   Forbid ();
  101.   if (tp->tp_flags & TPF_WANT_LOCK)
  102.     ix_wakeup (&tp->tp_flags);
  103.     
  104.   tp->tp_flags &= ~(TPF_WANT_LOCK|TPF_LOCKED);
  105.   Permit ();
  106. }
  107.  
  108.  
  109. int
  110. pipe (int pv[2])
  111. {
  112.   struct file *f1, *f2;
  113.   struct tmp_pipe *tp;
  114.   int res, err, omask;
  115.   
  116.   omask = syscall (SYS_sigsetmask, ~0);
  117.   res = -1; 
  118.   err = EMFILE;
  119.   if (tp = __pinit ())
  120.     {
  121.       if (! falloc (&f1, pv))
  122.         {
  123.           if (! falloc (&f2, pv+1))
  124.             {
  125.           f1->f_tp     = tp;
  126.           f1->f_stb.st_mode = 0666 | S_IFCHR;
  127.           f1->f_stb.st_size = PIPE_SIZE;
  128.           f1->f_stb.st_blksize = 512;
  129.           f1->f_flags  = FREAD;
  130.           f1->f_type   = DTYPE_PIPE;
  131.           f1->f_read   = __pread;
  132.           f1->f_write  = 0;
  133.           f1->f_ioctl  = __pioctl;
  134.           f1->f_close  = __pclose;
  135.           f1->f_select = __pselect;
  136.  
  137.           f2->f_tp     = tp;
  138.           f2->f_stb.st_mode = 0666 | S_IFCHR;
  139.           f2->f_stb.st_size = PIPE_SIZE;
  140.           f2->f_stb.st_blksize = 512;
  141.           f2->f_flags  = FWRITE;
  142.           f2->f_type   = DTYPE_PIPE;
  143.           f2->f_read   = 0;
  144.           f2->f_write  = __pwrite;
  145.           f2->f_ioctl  = __pioctl;
  146.           f2->f_close  = __pclose;
  147.           f2->f_select = __pselect;
  148.  
  149.           res = err =0;
  150.           goto ret;
  151.         }
  152.       f1->f_count = 0;
  153.     }
  154.  
  155.       kfree (tp);
  156.     }
  157.  
  158. ret:
  159.   syscall (SYS_sigsetmask, omask);
  160.  
  161.   errno = err;
  162.   KPRINTF_DISABLED (("&errno = %lx, errno = %ld\n", &errno, errno));
  163.   return res;
  164. }
  165.  
  166. static struct tmp_pipe *
  167. __pinit (void)
  168. {
  169.   struct tmp_pipe *tp = (struct tmp_pipe *) kmalloc (sizeof (*tp));
  170.   
  171.   if (tp)
  172.     {
  173.       tp->tp_flags = 0;
  174.       tp->tp_reader = tp->tp_writer = tp->tp_buffer;
  175.     }
  176.  
  177.   return tp;
  178. }
  179.  
  180. static int
  181. __pclose (struct file *f)
  182. {
  183.   int omask;
  184.  
  185.   ix_lock_base ();
  186.  
  187.   f->f_count--;
  188.  
  189.   if (f->f_count == 0)
  190.     {
  191.       if (f->f_read)
  192.         f->f_tp->tp_flags |= TPF_NO_READER;
  193.       else
  194.     f->f_tp->tp_flags |= TPF_NO_WRITER;
  195.     
  196.       if ((f->f_tp->tp_flags & (TPF_NO_READER|TPF_NO_WRITER)) ==
  197.       (TPF_NO_READER|TPF_NO_WRITER))
  198.     kfree (f->f_tp);
  199.       else
  200.     ix_wakeup (f->f_tp);
  201.     }
  202.  
  203.   ix_unlock_base ();
  204.  
  205.   return 0;
  206.   
  207. }
  208.  
  209. static int
  210. __pread (struct file *f, char *buf, int len)
  211. {
  212.   int omask = syscall (SYS_sigsetmask, ~0);
  213.   int err = errno;
  214.   int really_read = 0;
  215.   struct tmp_pipe *tp = f->f_tp;
  216.  
  217.   __get_pipe (f);
  218.  
  219.   while (len)
  220.     {
  221.       if (tp->tp_reader == tp->tp_writer)
  222.     {
  223.       KPRINTF_DISABLED (("__pread: len == %ld, buffer full\n", len));
  224.       if (tp->tp_flags & TPF_NO_WRITER)
  225.         {
  226.           KPRINTF_DISABLED (("__pread: EOF\n"));
  227.           err = 0;
  228.           break;
  229.         }
  230.     
  231.       if (f->f_flags & FNDELAY)
  232.         {
  233.           if (! really_read)
  234.         {
  235.           really_read = -1;
  236.           err = EAGAIN;
  237.         }
  238.           break;
  239.         }
  240.       else if (really_read)
  241.         {
  242.           err = 0;
  243.           break;
  244.         }
  245.       else
  246.         {
  247.           int sleep_rc;
  248.           KPRINTF_DISABLED (("__pread: going to sleep.\n"));
  249.           /* wait for something to be read or all readers to close */
  250.           Forbid ();
  251.           /* sigh.. Forbid() is necessary, or the other end may change
  252.              the pipe, and in the worst case also settle for sleep(), and
  253.              there it is.. deadlock.. */
  254.           __release_pipe (f);
  255.  
  256.           /* make write interruptible */
  257.           syscall (SYS_sigsetmask, omask);
  258.           sleep_rc = ix_sleep (tp, "pwrite");
  259.           Permit ();
  260.           if (sleep_rc < 0)
  261.             setrun (FindTask (0));
  262.           omask = syscall (SYS_sigsetmask, ~0);
  263.  
  264.           __get_pipe (f);
  265.           continue;        /* retry */
  266.         }
  267.     }
  268.       else
  269.     {
  270.       /* okay, there's something to read from the pipe */
  271.       if (tp->tp_reader > tp->tp_writer)
  272.         {
  273.           /* read till end of buffer and wrap around */
  274.           int avail = PIPE_SIZE - (tp->tp_reader - tp->tp_buffer);
  275.           int do_read = len < avail ? len : avail;
  276.  
  277.           /* KPRINTF_DISABLED (("__pread-1: reading %ld bytes.\n", do_read)); */
  278.  
  279.           really_read += do_read;
  280.           bcopy (tp->tp_reader, buf, do_read);
  281.           len -= do_read;
  282.           buf += do_read;
  283.           tp->tp_reader += do_read;
  284.           if (tp->tp_reader - tp->tp_buffer == PIPE_SIZE)
  285.         /* wrap around */
  286.         tp->tp_reader = tp->tp_buffer;
  287.         }
  288.       if (len && tp->tp_reader < tp->tp_writer)
  289.         {
  290.           int avail = tp->tp_writer - tp->tp_reader;
  291.           int do_read = len < avail ? len : avail;
  292.  
  293.           /* KPRINTF_DISABLED (("__pread-2: reading %ld bytes.\n", do_read)); */
  294.  
  295.           really_read += do_read;
  296.           bcopy (tp->tp_reader, buf, do_read);
  297.           tp->tp_reader += do_read;
  298.           len -= do_read;
  299.           buf += do_read;
  300.         }
  301.     }
  302.  
  303.       ix_wakeup (tp);
  304.     }
  305.  
  306.   __release_pipe (f);
  307.  
  308.   syscall (SYS_sigsetmask, omask);
  309.   errno = err;
  310.   KPRINTF_DISABLED (("&errno = %lx, errno = %ld\n", &errno, errno));
  311.   return really_read;
  312. }
  313.  
  314.  
  315. static int
  316. __pwrite (struct file *f, char *buf, int len)
  317. {
  318.   int  omask = syscall (SYS_sigsetmask, ~0);
  319.   int err = errno;
  320.   int really_written = 0;
  321.   struct tmp_pipe *tp = f->f_tp;
  322.  
  323.   __get_pipe (f);
  324.  
  325.   while (len)
  326.     {
  327.       if (tp->tp_flags & TPF_NO_READER)
  328.     {
  329.       KPRINTF_DISABLED (("__pwrite: SIGPIPE\n"));
  330.       really_written = -1;
  331.       err = EPIPE;
  332.       /* this is something no `real' Amiga pipe handler will do ;-)) */
  333.       _psignal (FindTask (0), SIGPIPE);
  334.       break;
  335.         }
  336.     
  337.       /* buffer full ?? */
  338.       if (tp->tp_reader == tp->tp_writer + 1
  339.       || (tp->tp_reader == tp->tp_buffer 
  340.           && tp->tp_writer == tp->tp_buffer + PIPE_SIZE - 1))
  341.     {
  342.       KPRINTF_DISABLED (("__pwrite: buffer full, len == %ld\n", len));
  343.       if (f->f_flags & FNDELAY)
  344.         {
  345.           if (! really_written)
  346.             {
  347.               really_written = -1;
  348.               err = EAGAIN;
  349.             }
  350.           break;
  351.         }
  352.       else
  353.         {
  354.           int sleep_rc;
  355.           KPRINTF_DISABLED (("__pwrite: going to sleep\n"));
  356.           /* wait for something to be read or all readers to close */
  357.           Forbid ();
  358.           /* sigh.. Forbid() is necessary, or the other end may change
  359.              the pipe, and in the worst case also settle for sleep(), and
  360.              there it is.. deadlock.. */
  361.           __release_pipe (f);
  362.  
  363.           /* make write interruptible */
  364.           syscall (SYS_sigsetmask, omask);
  365.           sleep_rc = ix_sleep (tp, "pwrite");
  366.           Permit ();
  367.           if (sleep_rc < 0)
  368.             setrun (FindTask (0));
  369.           omask = syscall (SYS_sigsetmask, ~0);
  370.  
  371.           __get_pipe (f);
  372.           continue;        /* retry */
  373.         }
  374.     }
  375.       else
  376.     {
  377.       /* okay, there's some space left to write to the pipe */
  378.  
  379.       if (tp->tp_writer >= tp->tp_reader)
  380.         {
  381.           /* write till end of buffer */
  382.           int avail = PIPE_SIZE - 1 - (tp->tp_writer - tp->tp_buffer);
  383.           int do_write;
  384.  
  385.           if (tp->tp_reader > tp->tp_buffer)
  386.             avail++;
  387.           do_write = len < avail ? len : avail;
  388.  
  389.           /* KPRINTF_DISABLED (("__pwrite-1: writing %ld bytes.\n", do_write)); */
  390.           really_written += do_write;
  391.           bcopy (buf, tp->tp_writer, do_write);
  392.           len -= do_write;
  393.           buf += do_write;
  394.           tp->tp_writer += do_write;
  395.           if (tp->tp_writer - tp->tp_buffer == PIPE_SIZE)
  396.             tp->tp_writer = tp->tp_buffer;
  397.         }
  398.  
  399.       if (tp->tp_writer < tp->tp_reader - 1)
  400.         {
  401.           int avail = tp->tp_reader - tp->tp_writer - 1;
  402.           int do_write = len < avail ? len : avail;
  403.  
  404.           /* KPRINTF_DISABLED (("__pwrite-2: writing %ld bytes.\n", do_write)); */
  405.           really_written += do_write;
  406.           bcopy (buf, tp->tp_writer, do_write);
  407.           tp->tp_writer += do_write;
  408.           len -= do_write;
  409.           buf += do_write;
  410.         }
  411.     }
  412.     
  413.       ix_wakeup (tp);
  414.     }
  415.  
  416.   __release_pipe (f);
  417.  
  418.   syscall (SYS_sigsetmask, omask);
  419.   errno = err;
  420.   KPRINTF_DISABLED (("&errno = %lx, errno = %ld\n", &errno, errno));
  421.   return really_written;
  422. }
  423.  
  424. static int
  425. __pselect (struct file *f, int select_cmd, int io_mode)
  426. {
  427.   struct tmp_pipe *tp = f->f_tp;
  428.  
  429.   /* I currently only check whether io is possible, no setup needed.
  430.      This would be quite different if select() waited the given timeout,
  431.      and wouldn't split the timeout into smaller slices */
  432.  
  433.   if (select_cmd == SELCMD_CHECK || select_cmd == SELCMD_POLL)
  434.     {
  435.       /* we support both, read and write checks (hey, something new ;-)) */
  436.       if (io_mode == SELMODE_IN)
  437.     return tp->tp_reader != tp->tp_writer;
  438.  
  439.       else if (io_mode == SELMODE_OUT)
  440.     return !(tp->tp_reader == tp->tp_writer + 1
  441.          || (tp->tp_reader == tp->tp_buffer 
  442.              && tp->tp_writer == tp->tp_buffer + PIPE_SIZE - 1));
  443.     }
  444.  
  445.   return 0;
  446. }
  447.  
  448. static int
  449. __pioctl (struct file *f, unsigned int cmd, unsigned int inout,
  450.           unsigned int arglen, unsigned int arg)
  451. {
  452.   int omask;
  453.   int result;
  454.   struct tmp_pipe *tp = f->f_tp;
  455.   
  456.   omask = syscall (SYS_sigsetmask, ~0);
  457.   __get_pipe (f);
  458.  
  459.   switch (cmd)
  460.     {
  461.     case FIONREAD:
  462.       {
  463.     unsigned int *pt = (unsigned int *)arg;
  464.     if (tp->tp_reader < tp->tp_writer)
  465.       *pt = tp->tp_writer - tp->tp_reader;
  466.     else if (tp->tp_reader > tp->tp_writer)
  467.       *pt = PIPE_SIZE - (tp->tp_reader - tp->tp_writer);
  468.     else
  469.       *pt = 0;
  470.     result = 0;
  471.         break;
  472.       }
  473.  
  474.     case FIONBIO:
  475.       {
  476.     result = f->f_flags & FNDELAY ? 1 : 0;
  477.     if (*(unsigned int *)arg)
  478.       f->f_flags |= FNDELAY;
  479.     else
  480.       f->f_flags &= ~FNDELAY;
  481.     /* I didn't find it documented in a manpage, but I assume, we
  482.      * should return the former state, not just zero.. */
  483.     break;
  484.       }
  485.  
  486.     case FIOASYNC:
  487.       {
  488.     /* DOESN'T WORK YET */
  489.  
  490.     int flags = *(unsigned long*)arg;
  491.     result = f->f_flags & FASYNC ? 1 : 0;
  492.     if (flags)
  493.       f->f_flags |= FASYNC;
  494.     else
  495.       f->f_flags &= ~FASYNC;
  496.  
  497.     /* ATTENTION: have to call some function here in the future !!! */
  498.  
  499.     /* I didn't find it documented in a manpage, but I assume, we
  500.      * should return the former state, not just zero.. */
  501.     break;
  502.       }
  503.  
  504.     case FIOCLEX:
  505.     case FIONCLEX:
  506.     case FIOSETOWN:
  507.     case FIOGETOWN:
  508.       /* this is no error, but nevertheless we don't take any actions.. */      
  509.       result = 0;
  510.       break;
  511.     }
  512.  
  513.   __release_pipe (f);
  514.   syscall (SYS_sigsetmask, omask);
  515.   return result;
  516. }
  517.